using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace ModWatch
{

	/// <summary>
	/// A <see cref="ModWatch.ModWatcherControlBase"/> control
	/// that provides users to track changes in a custom manner.
	/// </summary>
	[PersistChildren(false)]
	[ParseChildren(true)]
	public class CustomModWatcher : ModWatcherControlBase
	{

		/// <summary>
		/// Occurs when the control should be saved.
		/// </summary>
		public event EventHandler<CustomModWatcherSaveEventArgs> SavingChanges;

		/// <summary>
		/// Occurs when the control is queried to see if a change has been made.
		/// </summary>
		public event EventHandler<CustomModWatcherCheckChangeEventArgs> CheckingChange;

		/// <summary>
		/// Gets or sets the name of the javascript function that should
		/// execute on the client to determine if a change has occurred.
		/// </summary>
		public string ClientCheckChange
		{
			get { return GetProperty<string>("ClientCheckChange", null); }
			set { SetProperty("ClientCheckChange", value); }
		}

		/// <summary>
		/// The value of the control the last time a save was performed.
		/// </summary>
		private object SavedValue
		{
			get { return GetProperty<object>("SavedValue", null); }
			set { SetProperty("SavedValue", value); }
		}

		/// <summary>
		/// See <see cref="ModWatch.ModWatcherControlBase"/>
		/// </summary>
		public override void SaveTargetState()
		{
			if (SavingChanges == null)
				throw new ModWatchException(String.Format("The CustomModWatcher '{0}' fired event SavingChanges which wasn't handled.", this.ID));
			CustomModWatcherSaveEventArgs e = new CustomModWatcherSaveEventArgs();
			SavingChanges(this, e);
			this.SavedValue = e.SavedValue;
		}

		/// <summary>
		/// See <see cref="ModWatch.IModWatcher"/>
		/// </summary>
		protected override bool HasBeenChanged()
		{
			if (CheckingChange == null)
				throw new ModWatchException(String.Format("The CustomModWatcher '{0}' fired event CheckingChange which wasn't handled.", this.ID));
			CustomModWatcherCheckChangeEventArgs e = new CustomModWatcherCheckChangeEventArgs(this.SavedValue);
			CheckingChange(this, e);
			return e.HasChanged;
		}

		/// <summary>
		/// Raises the <see cref="System.Web.UI.Control.Init"/> event.
		/// </summary>
		/// <param name="e">
		/// An <see cref="System.EventArgs"/>
		/// object that contains event data.
		/// </param>
		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);

			this.GettingScriptReferences += new EventHandler<ScriptReferencesEventArgs>(this_GettingScriptReferences);
		}

		/// <summary>
		/// Returns the <see cref="System.Web.UI.ScriptDescriptor"/>s required by
		/// this instance of <see cref="ModWatch.TextBoxModWatcherExtender"/>.
		/// </summary>
		/// <returns>
		/// A collection of <see cref="System.Web.UI.ScriptDescriptor"/>s
		/// defining this instance of <see cref="ModWatch.TextBoxModWatcherExtender"/>.
		/// </returns>
		public override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
		{
			ScriptControlDescriptor sd = new ScriptControlDescriptor("ModWatch.CustomModWatcher", this.ClientID);
			sd.AddProperty("modGroup", this.ModGroup);
			sd.AddProperty("savedValue", this.SavedValue);
			if (this.ClientCheckChange == null)
				throw new ModWatchException(String.Format("The ClientCheckChange property of CustomModWatcher '{0}' cannot be null.", this.ID));
			sd.AddScriptProperty("checkChange", this.ClientCheckChange);

			return new ScriptDescriptor[] { sd };
		}

		/// <summary>
		/// Registers the scripts needed by the
		/// <see cref="ModWatch.TextBoxModWatcherExtender"/> class.
		/// </summary>
		/// <param name="sender">
		/// The <see cref="System.Object"/> that fired the
		/// <see cref="ModWatch.ModWatchExtenderBase.GettingScriptReferences"/> event.
		/// </param>
		/// <param name="e">
		/// A <see cref="ModWatch.ScriptReferencesEventArgs"/> object that contains the event data.
		/// </param>
		private void this_GettingScriptReferences(object sender, ScriptReferencesEventArgs e)
		{
			e.AddWebResourceScriptReference("ModWatch.Scripts.CustomModWatcherCheckChangeEventArgs.js");
			e.AddWebResourceScriptReference("ModWatch.Scripts.CustomModWatcher.js");
		}

	}

}
